/*
 * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package com.sun.corba.se.spi.orbutil.fsm;

import com.sun.corba.se.spi.orbutil.fsm.Input;
import com.sun.corba.se.spi.orbutil.fsm.Action;
import com.sun.corba.se.spi.orbutil.fsm.Guard;
import com.sun.corba.se.spi.orbutil.fsm.StateEngine;
import com.sun.corba.se.spi.orbutil.fsm.StateImpl;
import com.sun.corba.se.spi.orbutil.fsm.StateEngineFactory;
import com.sun.corba.se.spi.orbutil.fsm.FSM;

class TestInput {
    TestInput(Input value, String msg) {
        this.value = value;
        this.msg = msg;
    }

    public String toString() {
        return "Input " + value + " : " + msg;
    }

    public Input getInput() {
        return value;
    }

    Input value;
    String msg;
}

class TestAction1 implements Action {
    public void doIt(FSM fsm, Input in) {
        System.out.println("TestAction1:");
        System.out.println("\tlabel    = " + label);
        System.out.println("\toldState = " + oldState);
        System.out.println("\tnewState = " + newState);
        if (label != in)
            throw new Error("Unexcepted Input " + in);
        if (oldState != fsm.getState())
            throw new Error("Unexpected old State " + fsm.getState());
    }

    public TestAction1(State oldState, Input label, State newState) {
        this.oldState = oldState;
        this.newState = newState;
        this.label = label;
    }

    private State oldState;
    private Input label;
    private State newState;
}

class TestAction2 implements Action {
    private State oldState;
    private State newState;

    public void doIt(FSM fsm, Input in) {
        System.out.println("TestAction2:");
        System.out.println("\toldState = " + oldState);
        System.out.println("\tnewState = " + newState);
        System.out.println("\tinput    = " + in);
        if (oldState != fsm.getState())
            throw new Error("Unexpected old State " + fsm.getState());
    }

    public TestAction2(State oldState, State newState) {
        this.oldState = oldState;
        this.newState = newState;
    }
}

class TestAction3 implements Action {
    private State oldState;
    private Input label;

    public void doIt(FSM fsm, Input in) {
        System.out.println("TestAction1:");
        System.out.println("\tlabel    = " + label);
        System.out.println("\toldState = " + oldState);
        if (label != in)
            throw new Error("Unexcepted Input " + in);
    }

    public TestAction3(State oldState, Input label) {
        this.oldState = oldState;
        this.label = label;
    }
}

class NegateGuard implements Guard {
    Guard guard;

    public NegateGuard(Guard guard) {
        this.guard = guard;
    }

    public Guard.Result evaluate(FSM fsm, Input in) {
        return guard.evaluate(fsm, in).complement();
    }
}

class MyFSM extends FSMImpl {
    public MyFSM(StateEngine se) {
        super(se, FSMTest.STATE1);
    }

    public int counter = 0;
}

public class FSMTest {
    public static final State STATE1 = new StateImpl("1");
    public static final State STATE2 = new StateImpl("2");
    public static final State STATE3 = new StateImpl("3");
    public static final State STATE4 = new StateImpl("4");

    public static final Input INPUT1 = new InputImpl("1");
    public static final Input INPUT2 = new InputImpl("2");
    public static final Input INPUT3 = new InputImpl("3");
    public static final Input INPUT4 = new InputImpl("4");

    private Guard counterGuard = new Guard() {
        public Guard.Result evaluate(FSM fsm, Input in) {
            MyFSM mfsm = (MyFSM) fsm;
            return Guard.Result.convert(mfsm.counter < 3);
        }
    };

    private static void add1(StateEngine se, State oldState, Input in, State newState) {
        se.add(oldState, in, new TestAction1(oldState, in, newState), newState);
    }

    private static void add2(StateEngine se, State oldState, State newState) {
        se.setDefault(oldState, new TestAction2(oldState, newState), newState);
    }

    public static void main(String[] args) {
        TestAction3 ta3 = new TestAction3(STATE3, INPUT1);

        StateEngine se = StateEngineFactory.create();
        add1(se, STATE1, INPUT1, STATE1);
        add2(se, STATE1, STATE2);

        add1(se, STATE2, INPUT1, STATE2);
        add1(se, STATE2, INPUT2, STATE2);
        add1(se, STATE2, INPUT3, STATE1);
        add1(se, STATE2, INPUT4, STATE3);

        se.add(STATE3, INPUT1, ta3, STATE3);
        se.add(STATE3, INPUT1, ta3, STATE4);
        add1(se, STATE3, INPUT2, STATE1);
        add1(se, STATE3, INPUT3, STATE2);
        add1(se, STATE3, INPUT4, STATE2);

        MyFSM fsm = new MyFSM(se);
        TestInput in11 = new TestInput(INPUT1, "1.1");
        TestInput in12 = new TestInput(INPUT1, "1.2");
        TestInput in21 = new TestInput(INPUT2, "2.1");
        TestInput in22 = new TestInput(INPUT2, "2.2");
        TestInput in31 = new TestInput(INPUT3, "3.1");
        TestInput in32 = new TestInput(INPUT3, "3.2");
        TestInput in33 = new TestInput(INPUT3, "3.3");
        TestInput in41 = new TestInput(INPUT4, "4.1");

        fsm.doIt(in11.getInput());
        fsm.doIt(in12.getInput());
        fsm.doIt(in41.getInput());
        fsm.doIt(in11.getInput());
        fsm.doIt(in22.getInput());
        fsm.doIt(in31.getInput());
        fsm.doIt(in33.getInput());
        fsm.doIt(in41.getInput());
        fsm.doIt(in41.getInput());
        fsm.doIt(in41.getInput());
        fsm.doIt(in22.getInput());
        fsm.doIt(in32.getInput());
        fsm.doIt(in41.getInput());
        fsm.doIt(in11.getInput());
        fsm.doIt(in12.getInput());
        fsm.doIt(in11.getInput());
        fsm.doIt(in11.getInput());
        fsm.doIt(in11.getInput());
        fsm.doIt(in11.getInput());
        fsm.doIt(in11.getInput());
    }
}
